#include "ObjModel.h"
#include "../Game.h"

#include <iostream>

namespace Facets {

	using namespace irr;

	core::array<newton::IBody*> ObjModel::s_NonCollisionObjects;

	ObjModel::ObjModel(const core::stringc& mxml) {
//		if(m_MeshSceneNode)
//			m_MeshSceneNode->drop();
		m_Model = NULL;
		m_nameNode = NULL;
		changeModel(mxml);
	}

	ObjModel::~ObjModel() {
//		m_MeshSceneNode->removeAll();
		m_Model->remove();
	}

	void ObjModel::__update(const float& dt) {
		if(m_LockRotation) {
			core::vector3df tmp;
			tmp = m_Model->getNode()->getRotation();
			tmp.Z = 0;
			tmp.X = 0;
			m_Model->setRotation(tmp);
		}

	}

	void ObjModel::loadModel(const core::stringc& filename) {
		// Create a node for the loaded model.
		scene::IAnimatedMeshSceneNode* _MeshSceneNode = Game::CreateMeshNode(filename);
		// Create the Body structure
		newton::SBodyFromNode bodyData;
		bodyData.Type = newton::EBT_PRIMITIVE_CAPSULE;
		bodyData.Node = _MeshSceneNode;

		// Lock the rotation around anything but the Y axis.
		// TODO: Check for obsoletion with avoidRotationOnAllAxes()
		m_LockRotation = true;

		// Create the actual Newton body.
		m_Model = Game::s_World->createCharacterController(Game::s_World->createBody(bodyData));
		// Set the material to material #1 for testing purposes.
		// Properties of Material #1:
		// No friction.
		// Collides w/ terrain material.
		// Zero elasticity and zero softness.
		m_Model->setMaterial(Game::s_World->getAllMaterials()[1]);

		// Avoid all rotations. Ever. >:(
		Game::s_World->getUtils()->avoidRotationOnAllAxes(m_Model);

		// No reason for this since we set the variable earlier, but
		// just in case I move the option to the XML file I load from...
		if(m_LockRotation)
			m_Model->setRotationUpdate(false);

		// Just for doublechecking's sake, we don't want any magical
		// poof-through-the-walls models.
		m_Model->setContinuousCollisionMode(true);

		setNonCollision();
	}

	void ObjModel::applyTextureToModel(int texnum, const core::stringc& filename) {
		if(m_Model) {
			m_Model->getNode()->setMaterialTexture(texnum, Game::s_Device->getVideoDriver()->getTexture(filename.c_str()));
			m_Model->getNode()->setMaterialFlag(video::EMF_LIGHTING, false); // enable dynamic lighting
		}
	}

	void ObjModel::setAnimationSpeed() {
		if(m_Model) {
			dynamic_cast<scene::IAnimatedMeshSceneNode*>(m_Model->getNode())->setAnimationSpeed(m_AnimSpeed);
		}
	}

	void ObjModel::changeModel(const core::stringc& mxml) {
		m_ModelXMLName = mxml;
		// read configuration from xml file
		int texnum = 0;
		m_AnimSpeed = 0;
		m_Mass = 0;
		core::stringw tempname;
		if(m_Model)
			m_Model->remove();
		io::IXMLReader* xml =
			Game::s_Device->getFileSystem()->createXMLReader(mxml.c_str());
		while(xml && xml->read()) {
			switch(xml->getNodeType()) {
				case io::EXN_TEXT:
					break;
				case io::EXN_ELEMENT: {
						if (core::stringw("ModelFile") == xml->getNodeName())
							loadModel(xml->getAttributeValue(L"file"));
						else
						if (core::stringw("TextureFile") == xml->getNodeName())
							applyTextureToModel(texnum++, xml->getAttributeValue(L"file"));
						else
						if (core::stringw("AnimateSpeed") == xml->getNodeName())
							m_AnimSpeed = xml->getAttributeValueAsFloat(L"speed");
						else
						if (core::stringw("Mass") == xml->getNodeName()) {
							m_Mass = 10.0f * xml->getAttributeValueAsFloat(L"mass");
						}
						else if(core::stringw("Name") == xml->getNodeName()) {
							tempname = xml->getAttributeValue(L"name");
						}
					}
					break;
				default:
					break;
			}
		}
		if (xml)
			xml->drop(); // don't forget to delete the xml reader
		TitleCompositeNode* fff = Game::CreateTitleCompositeNode(m_Model->getNode());
		fff->addBar(L"Health",TCN_NORMAL_BAR);
		fff->addLabel(L"Name",tempname);
		fff->drop();
//		updateWeight(m_Mass);
	}

	void ObjModel::moveLateral(float multiplier) {
		core::vector3df tmp = m_Model->getVelocity();
		tmp.X = tmp.Z = 0;
		tmp += m_Model->FRIgetDirectionPositionY(core::vector3df(multiplier,0,0));
		m_Model->setVelocity(tmp);
	}

	void ObjModel::turn(float speed) {
		m_Model->getNode()->setRotation(core::vector3df(0,m_Model->getNode()->getRotation().Y+speed,0));
	}
	
	void ObjModel::createNameNode(const core::stringc& name) {
	}
	
	void ObjModel::setNameVisible(bool vis) {
		m_nameNode->setVisible(vis);
	}
	
	bool ObjModel::getNameVisible() {
		return m_nameNode->isVisible();
	}
}
